package com.wzcl.app.service.impl;

import com.wzcl.app.dao.model.Activity;
import com.wzcl.app.dao.model.FileGroup;
import com.wzcl.app.dao.model.FileModel;
import com.wzcl.app.dao.repository.FileModelRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.common.MyPage;
import com.wzcl.app.model.dto.FileModelDto;
import com.wzcl.app.service.FileGroupService;
import com.wzcl.app.service.FileModelService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Log4j2
@Service
@Transactional
public class FileModelServiceImpl implements FileModelService {

    @Autowired
    private FileModelRepository repository;

    @Autowired
    private FileGroupService fileGroupService;

    @Override
    public FileModel addFileModel(FileModelDto fileModelDto) {
        FileModel fileModel = new FileModel();
        BeanUtils.copyProperties(fileModelDto, fileModel);
        //校验素材组的存在性
        fileGroupService.getAndCheckById(fileModelDto.getFileGroupId());
        return repository.save(fileModel);
    }

    @Override
    public FileModel updateFileModel(FileModelDto fileModelDto) {
        FileModel fileModel = getAndCheckById(fileModelDto);
        BeanUtils.copyProperties(fileModelDto, fileModel, "id", "fileGroupId");
        return repository.save(fileModel);
    }

    @Override
    public void delFileModel(FileModelDto fileModelDto) {
        if (fileModelDto.getModelIdList() != null && fileModelDto.getModelIdList().size() > 0) {
            List<FileModel> fileModelList = repository.findAllById(fileModelDto.getModelIdList());
            if (fileModelList != null && fileModelList.size() > 0) {
                repository.deleteAll(fileModelList);
            }
            return;
        }
        throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少目标素材ID");
    }

    @Override
    public void copyFileModel(FileModelDto fileModelDto) {
        if (fileModelDto.getModelIdList() != null && fileModelDto.getFileGroupId() != null) {
            FileGroup group = fileGroupService.getAndCheckById(fileModelDto.getFileGroupId());
            if (fileModelDto.getModelIdList().size() > 0) {
                List<FileModel> fileModelList = repository.findAllById(fileModelDto.getModelIdList());
                if (fileModelList != null && fileModelList.size() > 0) {
                    List<FileModel> collect = fileModelList.stream().map(fileModel -> {
                        FileModel newModel = new FileModel();
                        BeanUtils.copyProperties(fileModel, newModel, "id", "fileGroupId");
                        newModel.setFileGroupId(group.getId());
                        return newModel;
                    }).collect(Collectors.toList());
                    repository.saveAll(collect);
                }
                return;
            }
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少目标素材ID");
        }
        throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少目的文件ID");
    }

    @Override
    public void copyFileModelAllGroup(Integer ordGroupId, Integer newGroupId) {
        List<FileModel> list = repository.findAllByFileGroupId(ordGroupId);
        if (list != null && list.size() > 0) {
            List<FileModel> collect = list.stream().map(fileModel -> {
                FileModel newModel = new FileModel();
                BeanUtils.copyProperties(fileModel, newModel, "id", "fileGroupId");
                newModel.setFileGroupId(newGroupId);
                return newModel;
            }).collect(Collectors.toList());
            repository.saveAll(collect);
        }
    }

    @Override
    public void moveFileModel(FileModelDto fileModelDto) {
        if (fileModelDto.getModelIdList() != null && fileModelDto.getFileGroupId() != null) {
            FileGroup group = fileGroupService.getAndCheckById(fileModelDto.getFileGroupId());
            if (fileModelDto.getModelIdList().size() > 0) {
                List<FileModel> fileModelList = repository.findAllById(fileModelDto.getModelIdList());
                if (fileModelList != null && fileModelList.size() > 0) {
                    fileModelList.stream().forEach(fileModel -> fileModel.setFileGroupId(group.getId()));
                    repository.saveAll(fileModelList);
                }
                return;
            }
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少目标素材ID");
        }
        throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少目的文件ID");
    }

    @Override
    public void delFileModelByGroupId(Integer id) {
        repository.deleteByFileGroupId(id);
    }

    @Override
    public FileModel getFileModelById(Integer id) {
        return repository.findById(id).orElse(null);
    }

    @Override
    public FileModel getAndCheckById(Integer id) {
        if (id == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少素材ID");
        }
        FileModel fileModel = getFileModelById(id);
        if (fileModel == null) {
            throw new BusinessException(CodeMsg.FILE_MODEL_NOT_EXIST);
        }
        return fileModel;
    }

    @Override
    public List<FileModel> getFileModelList(FileModelDto fileModelDto) {
        return repository.findAll(getSpecification(fileModelDto), fileModelDto.getSort());
    }

    @Override
    public MyPage<FileModel> getFileModelPage(FileModelDto fileModelDto) {
        Page<FileModel> all = repository.findAll(getSpecification(fileModelDto), fileModelDto.getPageable());
        ArrayList<FileModel> list = new ArrayList<>(all.getContent());
        Collections.reverse(list);
        MyPage<FileModel> myPage = new MyPage<>();
        myPage.setContent(list);
        myPage.setTotalElements(all.getTotalElements());
        return myPage;
    }

    private Specification<FileModel> getSpecification(FileModelDto fileModelDto) {
        return new Specification<FileModel>() {
            @Override
            public Predicate toPredicate(Root<FileModel> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if (StringUtils.isNotBlank(fileModelDto.getName())) {
                    predicates.add(criteriaBuilder.like(root.get("name"), "%" + fileModelDto.getName() + "%"));
                }
                if (fileModelDto.getFileGroupId() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("fileGroupId"), fileModelDto.getFileGroupId()));
                }
                if (fileModelDto.getType() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("type"), fileModelDto.getType()));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }
}
